#ifndef __KERN_TRAP_TRAP_H__
#define __KERN_TRAP_TRAP_H__

#include <types.h>

/* Trap Numbers */

/* Processor-defined: */
#define T_DIVIDE				0	// divide error
#define T_DEBUG					1	// debug exception
#define T_NMI					2	// non-maskable interrupt
#define T_BRKPT					3	// breakpoint
#define T_OFLOW					4	// overflow
#define T_BOUND					5	// bounds check
#define T_ILLOP					6	// illegal opcode
#define T_DEVICE				7	// device not available
#define T_DBLFLT				8	// double fault
// #define T_COPROC				9	// reserved (not used since 486)
#define T_TSS					10	// invalid task switch segment
#define T_SEGNP					11	// segment not present
#define T_STACK					12	// stack exception
#define T_GPFLT					13	// general protection fault
#define T_PGFLT					14	// page fault
// #define T_RES				15	// reserved
#define T_FPERR					16	// floating point error
#define T_ALIGN					17	// aligment check
#define T_MCHK					18	// machine check
#define T_SIMDERR				19	// SIMD floating point error

#define T_SYSCALL               0x80 // SYSCALL, ONLY FOR THIS PROJ

/* Hardware IRQ numbers. We receive these as (IRQ_OFFSET + IRQ_xx) */
#define IRQ_OFFSET				32	// IRQ 0 corresponds to int IRQ_OFFSET

#define IRQ_TIMER				0
#define IRQ_KBD					1
#define IRQ_COM1				4
#define IRQ_IDE1				14
#define IRQ_IDE2				15
#define IRQ_ERROR				19
#define IRQ_SPURIOUS			31

/* registers as pushed by pushal */
struct pushregs {
	uint32_t reg_edi;
	uint32_t reg_esi;
	uint32_t reg_ebp;
	uint32_t reg_oesp;			/* Useless */
	uint32_t reg_ebx;
	uint32_t reg_edx;
	uint32_t reg_ecx;
	uint32_t reg_eax;
};

struct trapframe {
	struct pushregs tf_regs;
	uint16_t tf_es;
	uint16_t tf_padding1;
	uint16_t tf_ds;
	uint16_t tf_padding2;
	uint32_t tf_trapno;
	/* below here defined by x86 hardware */
	uint32_t tf_err;
	uintptr_t tf_eip;
	uint16_t tf_cs;
	uint16_t tf_padding3;
	uint32_t tf_eflags;
	/* below here only when crossing rings, such as from user to kernel */
	uintptr_t tf_esp;
	uint16_t tf_ss;
	uint16_t tf_padding4;
};

void idt_init(void);
void print_trapframe(struct trapframe *tf);
void print_regs(struct pushregs *regs);
bool trap_in_kernel(struct trapframe *tf);

#endif /* !__KERN_TRAP_TRAP_H__ */

